﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.IO.IsolatedStorage;
using System.Text.RegularExpressions;

namespace API.WindowsLive.SkyDrive
{
    class SplitLargeFiles
    {
        static int bufferSize = 1024;
        static String pattern = @"^(.*)_(\d*)_(\d*).part$";
        long maxFileSize = 50000000; //50MB

        public Boolean isLargeFile(FileInfo fileInfo)
        {
            return fileInfo.Length > maxFileSize;
        }

        public SplitLargeFiles(long maxFileSize)
        {
            this.maxFileSize = maxFileSize;
        }

        public static Boolean isSplitFile(String fileName)
        {
            Regex regex = new Regex(pattern);
            return regex.IsMatch(fileName);
        }

        public static Boolean isFirstSplitFile(String partFileName)
        {
            Regex regex = new Regex(pattern);
            if (regex.IsMatch(partFileName))
            {
                return Int32.Parse(regex.Match(partFileName).Groups[2].Value) == 1;
            }

            return false;
        }

        public static String getFileName(String partFileName)
        {
            partFileName = partFileName.Replace("^_", "_");
            Regex regex = new Regex(pattern);
            if (regex.IsMatch(partFileName))
            {
                return regex.Match(partFileName).Groups[1].Value;
            }
            return null;
        }

        public static int getNumberOfFiles(String partFileName)
        {
            Regex regex = new Regex(pattern);
            partFileName = partFileName.Replace("^_", "_");

            if (regex.IsMatch(partFileName))
            {
                return Int32.Parse(regex.Match(partFileName).Groups[3].Value);
            }

            return 0;
        }

        public static String[] getAllFileNames(String partFileName)
        {
            Regex regex = new Regex(pattern);
            partFileName = partFileName.Replace("^_", "_");
            if (regex.IsMatch(partFileName))
            {
                String fileName = regex.Match(partFileName).Groups[1].Value;
                int currentFile = Int32.Parse(regex.Match(partFileName).Groups[2].Value);
                int numberOfFiles = Int32.Parse(regex.Match(partFileName).Groups[3].Value);

                String[] returnFileNames = new String[numberOfFiles];

                for (int i = 1; i <= numberOfFiles; i++)
                {
                    returnFileNames[i - 1] = String.Format("{0}_{1}_{2}.part", fileName, i, numberOfFiles);
                }

                return returnFileNames;
            }

            return new String[0];
        }

        public String[] Split(FileInfo file)
        {
            long totalSize = file.Length;
            int parts = (int)(totalSize / maxFileSize) + 1;
            String[] files = new String[parts];

            Guid newGuid = Guid.NewGuid();

            DirectoryInfo directeryInfo = new DirectoryInfo(newGuid.ToString());
            directeryInfo.Create();

            FileStream mainFileToSplit = new FileStream(file.FullName, FileMode.OpenOrCreate, FileAccess.Read);

            for (int i = 1; i <= parts; i++)
            {
                files[i - 1] = String.Format("{0}{1}{2}_{3}_{4}.part", directeryInfo.FullName, Path.DirectorySeparatorChar, file.Name, i, parts);
                FileStream filePart = new FileStream(files[i - 1], FileMode.OpenOrCreate, FileAccess.Write);
                int data = 0;
                long totalReadSoFar = 0;

                byte[] buffer = new byte[bufferSize + 1];
                while ((data = mainFileToSplit.Read(buffer, 0, bufferSize)) > 0)
                {
                    filePart.Write(buffer, 0, data);
                    totalReadSoFar += data;

                    if (totalReadSoFar + bufferSize > maxFileSize)
                        break;
                }
                filePart.Close();
            }
            mainFileToSplit.Close();

            return files;
        }

        public static void deleteFolder(String[] files)
        {
            DirectoryInfo parentDirectory = null;
            foreach (String fileName in files)
            {
                FileInfo fileInfo = new FileInfo(fileName);
                if (fileInfo.Exists)
                {
                    parentDirectory = fileInfo.Directory;
                    fileInfo.Delete();
                }
            }

            if (parentDirectory != null)
            {
                if (parentDirectory.Exists)
                    parentDirectory.Delete();
            }
        }

        public static void StichFileBack(String fileName, int partsNumber)
        {
            FileStream recontructedFile = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write);

            for (int i = 1; i <= partsNumber; i++)
            {
                FileStream filePart = new FileStream(String.Format("{0}_{1}_{2}.part", fileName, i, partsNumber), FileMode.OpenOrCreate, FileAccess.Read);

                int data = 0;

                byte[] buffer = new byte[bufferSize + 1];

                while ((data = filePart.Read(buffer, 0, bufferSize)) > 0)
                    recontructedFile.Write(buffer, 0, data);

                filePart.Close();
            }
            recontructedFile.Close();
        }
    }
}
